{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 标准数据类型\n",
    "**Python3 中有六个标准的数据类型：**\n",
    "\n",
    "- Number（数字）\n",
    "- String（字符串）\n",
    "- List（列表）\n",
    "- Tuple（元组）\n",
    "- Set（集合）\n",
    "- Dictionary（字典）\n",
    "\n",
    "**Python3 的六个标准数据类型中：**\n",
    "- 不可变数据（3 个）：Number（数字）、String（字符串）、Tuple（元组）；\n",
    "- 可变数据（3 个）：List（列表）、Dictionary（字典）、Set（集合）。\n",
    "\n",
    "### 补充：map()\n",
    "\n",
    "`map()` 会根据提供的函数对指定序列做映射。\n",
    "\n",
    "map() 函数语法：\n",
    "```py\n",
    "map(function, iterable, ...)\n",
    "```\n",
    "- function -- 函数\n",
    "- iterable -- 一个或多个序列\n",
    "\n",
    "### 补充：reduce()\n",
    "\n",
    "`reduce()` 函数会对参数序列中元素进行累积。\n",
    "\n",
    "reduce() 函数语法：\n",
    "```py\n",
    "reduce(function, iterable[, initializer])\n",
    "```\n",
    "- function -- 函数，有两个参数\n",
    "- iterable -- 可迭代对象\n",
    "- initializer -- 可选，初始参数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [sum_by](https://www.30secondsofcode.org/python/s/sum-by)\n",
    "Python, Math, List, Function, Beginner\n",
    "\n",
    "Returns the sum of a list, after mapping each element to a value using the provided function.\n",
    "\n",
    "Use `map()` with `fn` to map each element to a value using the provided function, use `sum()` to return the sum of the values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:12:39.413204Z",
     "start_time": "2020-08-27T14:12:39.408180Z"
    }
   },
   "outputs": [],
   "source": [
    "def sum_by(lst, fn):\n",
    "    return sum(map(fn, lst))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:12:50.658283Z",
     "start_time": "2020-08-27T14:12:50.649126Z"
    }
   },
   "outputs": [],
   "source": [
    "sum_by([{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }], lambda v : v['n'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [average_by](https://www.30secondsofcode.org/python/s/average-by)\n",
    "Python, Math, List, Function, Intermediate\n",
    "\n",
    "Returns the average of a list, after mapping each element to a value using the provided function.\n",
    "\n",
    "Use `map()` to map each element to the value returned by `fn`. Use `sum()` to sum all of the mapped values, divide by `len(lst)`.\n",
    "\n",
    "平均数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T12:57:56.743906Z",
     "start_time": "2020-08-27T12:57:56.737611Z"
    }
   },
   "outputs": [],
   "source": [
    "def average_by(lst, fn=lambda x: x):\n",
    "    return sum(map(fn, lst), 0.0) / len(lst)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T13:00:46.556776Z",
     "start_time": "2020-08-27T13:00:46.549515Z"
    },
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "print(average_by([{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }], lambda x: x['n']))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [median](https://www.30secondsofcode.org/python/s/median)\n",
    "Python, Math, Beginner\n",
    "\n",
    "Finds the median of a list of numbers.\n",
    "\n",
    "Sort the numbers of the list using `list.sort()` and find the median, which is either the middle element of the list if the list length is odd or the average of the two middle elements if the list length is even.\n",
    "\n",
    "`statistics.median()` provides similar functionality to this snippet.\n",
    "\n",
    "中位数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:17:58.775364Z",
     "start_time": "2020-08-27T14:17:58.767554Z"
    }
   },
   "outputs": [],
   "source": [
    "def median(list_):\n",
    "    list_.sort()  # 先进行排序\n",
    "    list_length = len(list_)\n",
    "    \n",
    "    if list_length % 2 == 0:  # 偶数\n",
    "        return (list_[int(list_length / 2) - 1] + list_[int(list_length / 2)]) / 2\n",
    "    return list_[int(list_length / 2)]  # 奇数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:18:00.412258Z",
     "start_time": "2020-08-27T14:18:00.405495Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.5\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "print(median([1,2,3,1]))\n",
    "print(median([1,2,3,4,5]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [max_by](https://www.30secondsofcode.org/python/s/max-by) & min_by\n",
    "Python, Math, List, Function, Beginner\n",
    "\n",
    "Returns the maximum value of a list, after mapping each element to a value using the provided function.\n",
    "\n",
    "Use `map()` with `fn` to map each element to a value using the provided function, use `max()` to return the maximum value.\n",
    "\n",
    "最大最小值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:06:09.231782Z",
     "start_time": "2020-08-27T14:06:09.227035Z"
    }
   },
   "outputs": [],
   "source": [
    "def max_by(lst, fn):\n",
    "    return max(map(fn, lst))\n",
    "\n",
    "def min_by(lst, fn):\n",
    "    return min(map(fn, lst))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:06:10.992751Z",
     "start_time": "2020-08-27T14:06:10.986168Z"
    }
   },
   "outputs": [],
   "source": [
    "print(max_by([{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }], lambda v : v['n']))\n",
    "print(min_by([{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }], lambda v : v['n']))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [digitize](https://www.30secondsofcode.org/python/s/digitize)\n",
    "Python, Math, List, Beginner\n",
    "\n",
    "Converts a number to a list of digits.\n",
    "\n",
    "Use `map()` combined with `int` on the string representation of `n` and return a list from the result.\n",
    "\n",
    "int 转 list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:17:04.168138Z",
     "start_time": "2020-08-27T14:17:04.163024Z"
    }
   },
   "outputs": [],
   "source": [
    "def digitize(n):\n",
    "    return list(map(int, str(n)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:17:06.469667Z",
     "start_time": "2020-08-27T14:17:06.456186Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "digitize(123)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:24:46.175735Z",
     "start_time": "2020-08-27T14:24:46.169181Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n",
      "[1, 2, 3, 4, 5]\n",
      "<class 'list'>\n"
     ]
    }
   ],
   "source": [
    "print(list(map(int, (1,2,3,4))))   # tuple\n",
    "print(list(map(int, \"12345\")))     # str"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [gcd](https://www.30secondsofcode.org/python/s/gcd)\n",
    "Python, Math, Beginner\n",
    "\n",
    "Calculates the greatest common divisor of a list of numbers.\n",
    "\n",
    "Use `functools.reduce()` and `math.gcd()` over the given list.\n",
    "\n",
    "最大公约数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:26:51.878834Z",
     "start_time": "2020-08-27T14:26:51.874479Z"
    }
   },
   "outputs": [],
   "source": [
    "from functools import reduce\n",
    "from math import gcd as _gcd\n",
    "\n",
    "def gcd(numbers):\n",
    "    return reduce(_gcd, numbers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:27:01.564606Z",
     "start_time": "2020-08-27T14:27:01.555698Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gcd([8, 36, 28])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [lcm](https://www.30secondsofcode.org/python/s/lcm)\n",
    "Python, Math, List, Recursion, Advanced\n",
    "\n",
    "Returns the least common multiple of a list of numbers.\n",
    "\n",
    "Use `functools.reduce()`, `math.gcd()` and `lcm(x,y) = x * y / gcd(x,y)` over the given list.\n",
    "\n",
    "最小公倍数\n",
    "\n",
    "`x * y / gcd(x, y)`：两个数的最小公倍数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:30:48.563776Z",
     "start_time": "2020-08-27T14:30:48.557448Z"
    }
   },
   "outputs": [],
   "source": [
    "from functools import reduce\n",
    "from math import gcd\n",
    "\n",
    "def lcm(numbers):\n",
    "    return reduce((lambda x, y: int(x * y / gcd(x, y))), numbers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:32:25.107828Z",
     "start_time": "2020-08-27T14:32:25.102726Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12\n",
      "60\n"
     ]
    }
   ],
   "source": [
    "print(lcm([12, 3, 4]))\n",
    "print(lcm([2, 3, 4, 5]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [clamp_number](https://www.30secondsofcode.org/python/s/clamp-number)\n",
    "Python, Math, Beginner\n",
    "\n",
    "Clamps `num` within the inclusive range specified by the boundary values `a` and `b`.\n",
    "\n",
    "If `num` falls within the range, return `num`. Otherwise, return the nearest number in the range.\n",
    "\n",
    "在边界值a和b指定的包含范围内的钳夹num。\n",
    "\n",
    "如果num在范围内，则返回num。否则，返回范围中最近的数字。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:48:55.014490Z",
     "start_time": "2020-08-27T14:48:55.007868Z"
    }
   },
   "outputs": [],
   "source": [
    "def clamp_number(num,a,b):\n",
    "    return max(min(num, max(a, b)), min(a, b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T14:49:28.014804Z",
     "start_time": "2020-08-27T14:49:28.007710Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "print(clamp_number(2, 3, 1))\n",
    "print(clamp_number(1, -1, 0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [fibonacci](https://www.30secondsofcode.org/python/s/fibonacci)\n",
    "Python, Math, List, Intermediate\n",
    "\n",
    "Generates a list, containing the Fibonacci sequence, up until the nth term.\n",
    "\n",
    "Starting with `0` and `1`, use `list.append()` to add the sum of the last two numbers of the list to the end of the list, until the length of the list reaches `n`.\n",
    "If `n` is less or equal to `0`, return a list containing `0`.\n",
    "\n",
    "[动态规划法](https://github.com/anlzou/algorithm-design-and-analysis/blob/master/chapters/chapter08-dynamic-programming/test8-1.md)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T15:17:52.655326Z",
     "start_time": "2020-08-27T15:17:52.649111Z"
    }
   },
   "outputs": [],
   "source": [
    "def fibonacci(n):\n",
    "    if n <= 0:\n",
    "        return [0]\n",
    "\n",
    "    sequence = [0, 1]\n",
    "    while len(sequence) <= n:\n",
    "        next_value = sequence[len(sequence) - 1] + sequence[len(sequence) - 2]\n",
    "        sequence.append(next_value)\n",
    "\n",
    "    return sequence"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T15:18:02.290877Z",
     "start_time": "2020-08-27T15:18:02.284062Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]\n"
     ]
    }
   ],
   "source": [
    "print(fibonacci(20))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T15:18:34.941590Z",
     "start_time": "2020-08-27T15:18:34.924465Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]\n"
     ]
    }
   ],
   "source": [
    "# 递归\n",
    "def fib_recur(n):\n",
    "    assert n >= 0, \"n > 0\"\n",
    "    if n <= 1:\n",
    "        return n\n",
    "    return fib_recur(n-1) + fib_recur(n-2)\n",
    "\n",
    "data = [fib_recur(i) for i in range(0, 21)]\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [in_range](https://www.30secondsofcode.org/python/s/in-range)\n",
    "Python, Math, Beginner\n",
    "\n",
    "Checks if the given number falls within the given range.\n",
    "\n",
    "Use arithmetic comparison to check if the given number is in the specified range. If the second parameter, `end`, is not specified, the range is considered to be from `0` to `start`.\n",
    "\n",
    "三元运算：`\"变量1\" if a>b else \"变量2\"`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T15:21:31.215408Z",
     "start_time": "2020-08-27T15:21:31.209807Z"
    }
   },
   "outputs": [],
   "source": [
    "def in_range(n, start, end = 0):\n",
    "    return start <= n <= end if end >= start else end <= n <= start"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T15:22:06.656869Z",
     "start_time": "2020-08-27T15:22:06.649449Z"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(in_range(3, 2, 5))\n",
    "print(in_range(3, 4))\n",
    "print(in_range(2, 3, 5))\n",
    "print(in_range(3, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [actorial](https://www.30secondsofcode.org/python/s/factorial)\n",
    "Python, Math, Recursion, Beginner\n",
    "\n",
    "Calculates the factorial of a number.\n",
    "\n",
    "Use recursion. If `num` is less than or equal to `1`, return `1`. Otherwise, return the product of `num` and the factorial of `num - 1`. Throws an exception if `num` is a negative or a floating point number.\n",
    "\n",
    "阶乘\n",
    "\n",
    "`python raise`：当程序出现错误，python会自动引发异常，也可以通过raise显示地引发异常。一旦执行了raise语句，raise后面的语句将不能执行。\n",
    " "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-28T08:52:08.108713Z",
     "start_time": "2020-08-28T08:52:08.097550Z"
    }
   },
   "outputs": [],
   "source": [
    "def factorial(num):\n",
    "    if not ((num >= 0) and (num % 1 == 0)):\n",
    "        raise Exception(\"Number can't be floating point or negative.\")\n",
    "    return 1 if num == 0 else num * factorial(num - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-28T08:52:54.587400Z",
     "start_time": "2020-08-28T08:52:54.579089Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "720\n"
     ]
    }
   ],
   "source": [
    "print(factorial(6))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
